/*
 * Copyrignt (c) xuzeshui.com. All Rights Reserved.
 * Author: Zeshui Xu<i@xuzeshui.com>
 * Created Time: 2015-11-15 13:49:33
 * Last Modified: 2015-11-15 20:31:46
 * File Name: avatar/avatar.go
 * Description:
 */
package avatar

import (
	"crypto/md5"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"passport/errorcode"
	"passport/models"

	log "github.com/cihub/seelog"
)

var (
	avatarService *AvatarService
)

/*
	头像上传请求
*/
type AvatarBase64UploadReq struct {
	Avatar string `json:"avatar"` //base64编码后的图像二进制数据
}

/*
	头像上传处理结果
*/
type AvatarBase64UploadResp struct {
	Url  string //头像URL
	Hash string //文件hash值
}

/*
	AvatarService
*/
type AvatarService struct{}

/*
	获取存储路径
*/
func (p *AvatarService) getAvatarFilePath(avatarHash string) (string, bool) {
	if len(avatarHash) != 32 {
		return "", false
	}
	baseDir := models.GetAvatarStoreDir()
	r := strings.SplitAfterN(avatarHash, "", 4)
	sub1 := r[0]
	sub2 := r[1]
	sub3 := r[2]
	filename := fmt.Sprintf("%s.jpg", r[3])
	return filepath.Join(baseDir, sub1, sub2, sub3, filename), true
}

/*
	根据hash获取头像的URL地址
*/
func (p *AvatarService) getAvatarURL(avatarHash string) (string, bool) {
	if len(avatarHash) != 32 {
		return "", false
	}
	urlPrefix := models.GetAvatarURLPrefix()
	r := strings.SplitAfterN(avatarHash, "", 4)
	sub1 := r[0]
	sub2 := r[1]
	sub3 := r[2]
	filename := fmt.Sprintf("%s.jpg", r[3])
	return fmt.Sprintf("%s/%s/%s/%s/%s", urlPrefix, sub1, sub2, sub3, filename), true
}

/*
	头像上传处理
*/
func (p *AvatarService) Base64Upload(req *AvatarBase64UploadReq) (uint, string, *AvatarBase64UploadResp) {
	if req == nil {
		return errorcode.EC_AVATAR_BASE64_UPLOAD_REQUEST_NULL, "invalid request params", nil
	}

	if req.Avatar == "" {
		return errorcode.EC_AVATAR_BASE64_UPLOAD_EMPTY, "empty data", nil
	}

	resp := &AvatarBase64UploadResp{}
	if avatarData, err := base64.StdEncoding.DecodeString(req.Avatar); err == nil {
		avatarHash := fmt.Sprintf("%x", md5.Sum(avatarData))
		picPath, _ := p.getAvatarFilePath(avatarHash)
		avatarUrl, _ := p.getAvatarURL(avatarHash)

		resp.Url = avatarUrl
		resp.Hash = avatarHash

		needSave := true
		if fi, err := os.Stat(picPath); err == nil { //文件存在
			if fi.Size() == int64(len(avatarData)) { //文件存在,且一模一样
				needSave = false
			} else { //文件存在,但大小不同,需要重写
				log.Warnf("avatar upload same file, but filesize is not same. avatarHash: %s", avatarHash)
			}
		} else { //文件不存在
			dirs := filepath.Dir(picPath)            //获取目录
			if _, err := os.Stat(dirs); err != nil { //目录不存在
				os.MkdirAll(dirs, 0755)
			}
		}
		if needSave {
			if err := ioutil.WriteFile(picPath, avatarData, 0644); err == nil {
				log.Infof("avatar upload success for avatar hash: %s, size: %d", avatarHash, len(avatarData))
			} else {
				log.Warnf("avatar upload failed for savin. avatar hash: %s, size: %d, error: %s", avatarHash, len(avatarData), err.Error())
				return errorcode.EC_AVATAR_BASE64_UPLOAD_SAVING_ERROR, "upload saving error", nil
			}
		} else {
			log.Warnf("avatar upload the same for filehash: %s", avatarHash)
		}
	} else {
		log.Warnf("Base64Upload error: %s", err.Error())
		return errorcode.EC_AVATAR_BASE64_UPLOAD_ERROR, "upload avatar error", nil
	}
	return errorcode.EC_GL_SUCCESS, errorcode.Msg(errorcode.EC_GL_SUCCESS), resp
}

/*
	获取AvatarService处理对象
*/
func GetAvatarService() *AvatarService {
	return avatarService
}

/*
	获取头像URL
*/
func GetAvatarURL(avatarHash string) (string, bool) {
	return avatarService.getAvatarURL(avatarHash)
}

func init() {
	avatarService = &AvatarService{}
}
